package net.beyondts.mplug;

import net.beyondts.mplug.utils.BeanFactory;
import org.apache.commons.lang3.reflect.MethodUtils;

import java.lang.reflect.InvocationTargetException;

/**
 * If you want to get a bean managed by main project's spring from a plugin project, you should use this tool class.
 *
 * @author blazecrystal
 */
public final class SpringBeansInvocation {
    /**
     * Invoke method of beans in main project according the bean's name.
     * @param beanName String bean name in Spring Context
     * @param methodName String method name
     * @param args Object... method args
     * @return Object the return object of the method, maybe void
     * @throws NoSuchMethodException ...
     * @throws IllegalAccessException ...
     * @throws InvocationTargetException ...
     */
    public static Object invokeByBeanName(String beanName, String methodName, Object... args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        return MethodUtils.invokeMethod(findByBeanName(beanName), true, methodName, args);
    }

    /**
     * Invoke method of beans in main project according the bean's type.
     * @param className String bean type class
     * @param methodName String method name
     * @param args Object... method args
     * @return Object the return object of the method, maybe void
     * @throws ClassNotFoundException ...
     * @throws NoSuchMethodException ...
     * @throws IllegalAccessException ..
     * @throws InvocationTargetException ...
     */
    public static Object invokeByBeanClass(String className, String methodName, Object... args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        return MethodUtils.invokeMethod(findByBeanClass(className), true, methodName, args);
    }

    /**
     * Get the bean managed by main project's Spring Context according its name.
     * @param beanName String bean name in main project's Spring Context
     * @return Object target bean instance
     */
    public static Object findByBeanName(String beanName) {
        return BeanFactory.getBean(beanName);
    }

    /**
     * Get the bean managed by main project's Spring Context according its type class name.
     * @param className String bean's type class name
     * @return Object target bean instance
     * @throws ClassNotFoundException ...
     */
    public static Object findByBeanClass(String className) throws ClassNotFoundException {
        return BeanFactory.getBean(Class.forName(className));
    }
}
